home *** CD-ROM | disk | FTP | other *** search
/ EnigmA Amiga Run 1996 February / EnigmA AMIGA RUN 04 (1996)(G.R. Edizioni)(IT)[!][issue 1996-02][Skylink CD III].iso / earcd / comm2 / xprz351s.lha / Zm.c < prev    next >
C/C++ Source or Header  |  1994-11-18  |  24KB  |  937 lines

  1. /**********************************************************************
  2.  *   Z M . C
  3.  *    ZMODEM protocol primitives
  4.  *    01-19-87  Chuck Forsberg Omen Technology Inc
  5.  *
  6.  * 29 July 89:
  7.  * Major overhaul by Rick Huebner for adaptation to Amiga XPR protocol spec
  8.  *
  9.  * 28 October 89:
  10.  * Converted to Lattice C 5.04
  11.  *
  12.  * 15 November 1991
  13.  * Code added to support CRC-32 by William M. Perkins.
  14.  *
  15.  * Version 2.63, 30 July 1993 build in locale, by Rainer Hess
  16.  **********************************************************************/
  17.  
  18. #include "xprzmodem_all.h"
  19. #include "Zcrc.h"
  20.  
  21. #define CATCOMP_NUMBERS
  22. #include "xprzmodem_catalog.h"
  23.  
  24. static char *frametypes[] =
  25. {
  26.   "Carrier Lost",                /* -3 */
  27.   "TIMEOUT",                        /* -2 */
  28.   "ERROR",                        /* -1 */
  29. #define FTOFFSET 3
  30.   "ZRQINIT",
  31.   "ZRINIT",
  32.   "ZSINIT",
  33.   "ZACK",
  34.   "ZFILE",
  35.   "ZSKIP",
  36.   "ZNAK",
  37.   "ZABORT",
  38.   "ZFIN",
  39.   "ZRPOS",
  40.   "ZDATA",
  41.   "ZEOF",
  42.   "ZFERR",
  43.   "ZCRC",
  44.   "ZCHALLENGE",
  45.   "ZCOMPL",
  46.   "ZCAN",
  47.   "ZFREECNT",
  48.   "ZCOMMAND",
  49.   "ZSTDERR",
  50.   "xxxxx"
  51. #define FRTYPES 22                /* Total number of frame types in this array */
  52.             /*  not including psuedo negative entries */
  53. };
  54.  
  55. static UBYTE DLE_actions[] =
  56. {
  57.   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 1, 1, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0,
  58.   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
  59.   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
  60.   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
  61.  
  62.   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 1, 1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
  63.   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
  64.   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
  65.   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
  66. };
  67. static UBYTE ZDLE_actions[] =
  68. {
  69.   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0,
  70.   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
  71.   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
  72.   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
  73.  
  74.   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
  75.   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
  76.   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
  77.   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
  78. };
  79.  
  80. /**********************************************************
  81.  *      void zsbhdr(struct Vars *v, USHORT type)
  82.  *
  83.  * Send ZMODEM binary header hdr of type type
  84.  **********************************************************/
  85. void
  86. zsbhdr (struct Vars *v, USHORT type)
  87. {
  88.   UBYTE *hdr = v->Txhdr;
  89.   short n;
  90.   USHORT crc;
  91.   ULONG crc32;
  92.  
  93. #ifdef DEBUGLOG
  94.   D (DEBUGINFO);
  95. #endif
  96.  
  97.   xsendline (v, ZPAD);
  98.   xsendline (v, ZDLE);
  99.  
  100.   if (v->Crc32t = v->Txfcs32)        /* zsbh32() */
  101.     {
  102.       xsendline (v, ZBIN32);
  103.       zsendline (v, (UBYTE) type);
  104.  
  105. #ifdef DEBUGLOG
  106.       xprsprintf (v->Msgbuf, "zsbh32: %s %lx\n", frametypes[type + FTOFFSET],
  107.                   v->Txpos);
  108.       dlog (v, v->Msgbuf);
  109.       D (DEBUGINFO);
  110. #endif
  111.       crc32 = 0xFFFFFFFFL;
  112.       crc32 = UPDC32 (type, crc32);
  113.  
  114.       for (n = 4; --n >= 0; ++hdr)
  115.       {
  116.         crc32 = UPDC32 ((0377 & *hdr), crc32);
  117.         zsendline (v, *hdr);
  118.       }
  119.       crc32 = ~crc32;
  120.       for (n = 4; --n >= 0;)
  121.         {
  122.           zsendline (v, (int) crc32);
  123.           crc32 >>= 8;
  124.         }
  125.     }
  126.   else
  127.     {
  128.       xsendline (v, ZBIN);
  129.       zsendline (v, (UBYTE) type);
  130.  
  131. #ifdef DEBUGLOG
  132.       xprsprintf (v->Msgbuf, "zsbhdr: %s %lx\n", frametypes[type + FTOFFSET],
  133.                   v->Txpos);
  134.       dlog (v, v->Msgbuf);
  135.       D (DEBUGINFO);
  136. #endif
  137.       crc = updcrc (type, 0);
  138.       for (n = 4; --n >= 0;)
  139.         {
  140.           zsendline (v, *hdr);
  141.           crc = updcrc (((USHORT) (*hdr++)), crc);
  142.         }
  143.  
  144.       crc = updcrc (((USHORT) 0), crc);
  145.       crc = updcrc (((USHORT) 0), crc);
  146.       zsendline (v, (UBYTE) (crc >> 8));
  147.       zsendline (v, (UBYTE) crc);
  148.     }
  149. }                                /* End of void zsbhdr() */
  150.  
  151. /**********************************************************
  152.  *      void zshhdr(struct Vars *v, USHORT type)
  153.  *
  154.  * Send ZMODEM HEX header hdr of type type
  155.  **********************************************************/
  156. void 
  157. zshhdr (struct Vars *v, USHORT type)
  158. {
  159.   UBYTE *hdr = v->Txhdr;
  160.   short n;
  161.   USHORT crc;
  162.  
  163. #ifdef DEBUGLOG
  164.   xprsprintf (v->Msgbuf, "zshhdr: %s %lx\n", frametypes[type + FTOFFSET],
  165.               v->Rxbytes);
  166.   dlog (v, v->Msgbuf);
  167.   D (DEBUGINFO);
  168. #endif
  169.   sendline (v, ZPAD);
  170.   sendline (v, ZPAD);
  171.   sendline (v, ZDLE);
  172.   sendline (v, ZHEX);
  173.   zputhex (v, (UBYTE) type);
  174.   v->Crc32t = 0;
  175.  
  176.   crc = updcrc (type, 0);
  177.   for (n = 4; --n >= 0;)
  178.     {
  179.       zputhex (v, *hdr);
  180.       crc = updcrc (((USHORT) (*hdr++)), crc);
  181.     }
  182.  
  183.   crc = updcrc (((USHORT) 0), crc);
  184.   crc = updcrc (((USHORT) 0), crc);
  185.   zputhex (v, (UBYTE) (crc >> 8));
  186.   zputhex (v, (UBYTE) crc);
  187.  
  188.   /* Make it printable on remote machine */
  189.   sendline (v, '\r');
  190.   sendline (v, '\n');
  191.   /* Uncork the remote in case a fake XOFF has stopped data flow */
  192.   if (type != ZFIN)
  193.     sendline (v, XON);
  194. }                                /* End of void zshhdr() */
  195.  
  196. /**********************************************************
  197.  *      void zsdata() and void zsda32()
  198.  *
  199.  * Send binary array buf of length length, with ending
  200.  * ZDLE sequence frameend
  201.  **********************************************************/
  202. void 
  203. zsdata (struct Vars *v, short length, USHORT frameend)
  204. {
  205.   UBYTE *buf, *outptr, c;
  206.   USHORT crc;
  207.   ULONG crc32;
  208.  
  209. #ifdef DEBUGLOG
  210.   xprsprintf (v->Msgbuf, v->Crc32t ? "zsda32: length=%ld end=%lx\n"
  211.           : "zsdata: length=%ld end=%lx\n", (long) length, (long) frameend);
  212.   dlog (v, v->Msgbuf);
  213.   D (DEBUGINFO);
  214. #endif
  215.  
  216.   buf = v->Pktbuf;
  217.   outptr = v->Outbuf + v->Outbuflen;
  218.   crc32 = 0xFFFFFFFFL;                /* zsda32() */
  219.   crc = 0;
  220.  
  221.   while (--length >= 0)
  222.     {
  223.       if (v->dzap)  /* If DirectZap enabled */
  224.       { 
  225. /*        c = *buf;
  226.         if (c == ZDLE || c == ZDLEE)
  227.         {
  228.           *outptr++ = ZDLE;
  229.           c ^= 0x40;
  230.         }
  231.         *outptr++ = v->Lastzsent = c;
  232. */
  233.         switch (ZDLE_actions[c = *buf])
  234.         {
  235.           case 1:
  236.             *outptr++ = ZDLE;
  237.             c ^= 0x40;
  238.           case 0:
  239.             *outptr++ = v->Lastzsent = c;
  240.         }
  241.       }
  242.       else
  243.       {    
  244.         switch (DLE_actions[c = *buf])
  245.         {
  246.           case 2:
  247.             if (v->Lastzsent != '@')
  248.               goto sendit;
  249.             /* Fallthrough */
  250.           case 1:
  251.             *outptr++ = ZDLE;
  252.             c ^= 0x40;
  253.           sendit:
  254.           case 0:
  255.             *outptr++ = v->Lastzsent = c;
  256.         }
  257.       } 
  258.       if (v->Crc32t)                /* zsda32() */
  259.         crc32 = UPDC32 ((0xFF & *buf++), crc32);
  260.       else
  261.         crc = updcrc (((USHORT) (*buf++)), crc);
  262.     }
  263.   *outptr++ = ZDLE;
  264.   *outptr++ = frameend;
  265.   v->Outbuflen = outptr - v->Outbuf;
  266.  
  267.   if (v->Crc32t)                /* zsda32() */
  268.     {
  269.       crc32 = UPDC32 (frameend, crc32);
  270.       crc32 = ~crc32;
  271.       for (length = 4; --length >= 0;)
  272.         {
  273.           zsendline (v, (int) crc32);
  274.           crc32 >>= 8;
  275.         }
  276.     }
  277.   else
  278.     {
  279.       crc = updcrc (frameend, crc);
  280.       crc = updcrc (((USHORT) 0), crc);
  281.       crc = updcrc (((USHORT) 0), crc);
  282.       zsendline (v, (UBYTE) (crc >> 8));
  283.       zsendline (v, (UBYTE) crc);
  284.     }
  285.  
  286.   if (frameend == ZCRCW)
  287.     xsendline (v, XON);
  288. }                                /* End of void zsdata() */
  289.  
  290. /**********************************************************
  291.  *      short zrdata(struct Vars *v, UBYTE *buf, short length)
  292.  *
  293.  * Receive array buf of max length with ending ZDLE sequence
  294.  * and CRC-16.  Returns the ending character or error code.
  295.  **********************************************************/
  296. short
  297. zrdata (struct Vars *v, UBYTE * buf, short length)
  298. {
  299.   short c, d;
  300.   USHORT crc;
  301.  
  302. #ifdef DEBUGLOG
  303.   D (DEBUGINFO);
  304. #endif
  305.  
  306.   if (v->Rxframeind == ZBIN32)
  307.     return zrdat32 (v, buf, length);
  308.  
  309.   crc = v->Rxcount = 0;
  310.   for (;;)
  311.     {
  312.       if ((c = zdlread (v)) & ~0xFF)
  313.         {
  314.         crcfoo:
  315.           switch (c)
  316.             {
  317.             case GOTCRCE:
  318.             case GOTCRCG:
  319.             case GOTCRCQ:
  320.             case GOTCRCW:
  321.               crc = updcrc (((d = c) & 0xFF), crc);
  322.               if ((c = zdlread (v)) & ~0xFF)
  323.                 goto crcfoo;
  324.               crc = updcrc (c, crc);
  325.               if ((c = zdlread (v)) & ~0xFF)
  326.                 goto crcfoo;
  327.               crc = updcrc (c, crc);
  328.               if (crc & 0xFFFF)
  329.                 {
  330.                   strcpy (v->Msgbuf, GetLocalString( &li, MSG_BAD_DATA_PACKET_CRC_16 ));
  331.                   return ERROR;
  332.                 }
  333. #ifdef DEBUGLOG
  334.               xprsprintf (v->Msgbuf, "zrdata: cnt = %ld ret = %lx\n",
  335.                           (long) v->Rxcount, (long) d);
  336.               dlog (v, v->Msgbuf);
  337.               D (DEBUGINFO);
  338. #endif
  339.               return d;
  340.             case GOTCAN:
  341.               strcpy (v->Msgbuf, GetLocalString( &li, MSG_SENDER_CANCELED ));
  342.               return ZCAN;
  343.             case TIMEOUT:
  344.               strcpy (v->Msgbuf, GetLocalString( &li, MSG_DATA_PACKET_TIMEOUT ));
  345.               return c;
  346.             case RCDO:
  347.               return c;
  348.             default:
  349.               strcpy (v->Msgbuf, GetLocalString( &li, MSG_UNRECOG_DATA_PACKET ));
  350.               return c;
  351.             }
  352.         }
  353.       if (--length < 0)
  354.         {
  355.           strcpy (v->Msgbuf, GetLocalString( &li, MSG_DATA_PACKET_TOO_LONG ));
  356.           return ERROR;
  357.         }
  358.       ++v->Rxcount;
  359.       *buf++ = c;
  360.       crc = updcrc (c, crc);
  361.       continue;
  362.     }
  363. }                                /* End of short zrdata() */
  364.  
  365. /**********************************************************
  366.  *      short zrdat32(struct Vars *v, UBYTE *buf, short length)
  367.  *
  368.  * Receive array buf of max length with ending ZDLE sequence
  369.  * and CRC-32.  Returns the ending character or error code.
  370.  **********************************************************/
  371. short
  372. zrdat32 (struct Vars *v, UBYTE * buf, short length)
  373. {
  374.   short c, d;
  375.   ULONG crc32;
  376.  
  377. #ifdef DEBUGLOG
  378.   D (DEBUGINFO);
  379. #endif
  380.  
  381.   crc32 = 0xFFFFFFFFL;
  382.   v->Rxcount = 0;
  383.  
  384.   for (;;)
  385.     {
  386.       if ((c = zdlread (v)) & ~0xFF)
  387.         {
  388.         crcfoo:
  389.           switch (c)
  390.             {
  391.             case GOTCRCE:
  392.             case GOTCRCG:
  393.             case GOTCRCQ:
  394.             case GOTCRCW:
  395.               d = c;
  396.               c &= 0xFF;
  397.               crc32 = UPDC32 (c, crc32);
  398.               if ((c = zdlread (v)) & ~0xFF)
  399.                 goto crcfoo;
  400.               crc32 = UPDC32 (c, crc32);
  401.               if ((c = zdlread (v)) & ~0xFF)
  402.                 goto crcfoo;
  403.               crc32 = UPDC32 (c, crc32);
  404.               if ((c = zdlread (v)) & ~0xFF)
  405.                 goto crcfoo;
  406.               crc32 = UPDC32 (c, crc32);
  407.               if ((c = zdlread (v)) & ~0xFF)
  408.                 goto crcfoo;
  409.               crc32 = UPDC32 (c, crc32);
  410.               if (crc32 != 0xDEBB20E3)
  411.                 {
  412.                   strcpy (v->Msgbuf, GetLocalString( &li, MSG_BAD_DATA_PACKET_CRC_32 ));
  413.                   return ERROR;
  414.                 }
  415. #ifdef DEBUGLOG
  416.               xprsprintf (v->Msgbuf, "zrdat32: cnt = %ld ret = %lx\n",
  417.                           (long) v->Rxcount, (long) d);
  418.               dlog (v, v->Msgbuf);
  419.               D (DEBUGINFO);
  420. #endif
  421.               return d;
  422.             case GOTCAN:
  423.               strcpy (v->Msgbuf, GetLocalString( &li, MSG_SENDER_CANCELED ));
  424.               return ZCAN;
  425.             case TIMEOUT:
  426.               strcpy (v->Msgbuf, GetLocalString( &li, MSG_DATA_PACKET_TIMEOUT ));
  427.               return c;
  428.             case RCDO:
  429.               return c;
  430.             default:
  431.               strcpy (v->Msgbuf, GetLocalString( &li, MSG_UNRECOG_DATA_PACKET ));
  432.               return c;
  433.             }
  434.         }
  435.       if (--length < 0)
  436.         {
  437.           strcpy (v->Msgbuf, GetLocalString( &li, MSG_DATA_PACKET_TOO_LONG ));
  438.           return ERROR;
  439.         }
  440.       ++v->Rxcount;
  441.       *buf++ = c;
  442.       crc32 = UPDC32 (c, crc32);
  443.       continue;
  444.     }
  445. }                                /* End of short zrdat32() */
  446.  
  447. /**********************************************************
  448.  *      short zgethdr(struct Vars *v)
  449.  *
  450.  * Read a ZMODEM header to hdr, either binary or hex.
  451.  *  On success return type of header.
  452.  *  Otherwise return negative on error.
  453.  **********************************************************/
  454. short
  455. zgethdr (struct Vars *v)
  456. {
  457.   short c, cancount;
  458.   long n;
  459. #ifdef DEBUGLOG
  460.   UBYTE msgbuf[128];
  461.  
  462.   D (DEBUGINFO);
  463. #endif
  464. /*fix to 2xmaxblk */
  465.   n = v->Baud;                        /* Max characters before start of frame */
  466.   cancount = 5;
  467. again:
  468.   v->Rxframeind = v->Rxtype = 0;
  469.   switch (c = noxrd7 (v))
  470.     {
  471.     case RCDO:
  472.     case TIMEOUT:
  473.       goto fifi;
  474.     case CAN:
  475.       if (--cancount <= 0)
  476.         {
  477.           c = ZCAN;
  478.           goto fifi;
  479.         }
  480.     default:
  481.     agn2:
  482.       if (--n <= 0)
  483.         {
  484.           strcpy (v->Msgbuf, GetLocalString( &li, MSG_HEADER_SEARCH_GARBAGE ));
  485.           return ERROR;
  486.         }
  487.       if (c != CAN)
  488.         cancount = 5;
  489.       goto again;
  490.     case ZPAD:                        /* This is what we want. */
  491.       break;
  492.     }
  493.   cancount = 5;
  494. splat:
  495.   switch (c = noxrd7 (v))
  496.     {
  497.     case ZPAD:
  498.       goto splat;
  499.     case RCDO:
  500.     case TIMEOUT:
  501.       goto fifi;
  502.     default:
  503.       goto agn2;
  504.     case ZDLE:                        /* This is what we want. */
  505.       break;
  506.     }
  507.  
  508.   switch (c = noxrd7 (v))
  509.     {
  510.     case RCDO:
  511.     case TIMEOUT:
  512.       goto fifi;
  513.     case ZBIN:
  514.       v->Rxframeind = ZBIN;
  515.       v->Crc32 = FALSE;
  516.       c = zrbhdr (v);
  517.       break;
  518.     case ZBIN32:
  519.       v->Crc32 = v->Rxframeind = ZBIN32;
  520.       c = zrbhdr32 (v);
  521.       break;
  522.     case ZHEX:
  523.       v->Rxframeind = ZHEX;
  524.       v->Crc32 = FALSE;
  525.       c = zrhhdr (v);
  526.       break;
  527.     case CAN:
  528.       if (--cancount <= 0)
  529.         {
  530.           c = ZCAN;
  531.           goto fifi;
  532.         }
  533.       goto agn2;
  534.     default:
  535.       goto agn2;
  536.     }
  537.   v->Rxpos = rclhdr (v);
  538. fifi:
  539.   switch (c)
  540.     {
  541.     case GOTCAN:
  542.       c = ZCAN;
  543.     case ZNAK:
  544.     case ZCAN:
  545.     case ERROR:
  546.     case TIMEOUT:
  547.     case RCDO:
  548.       xprsprintf (v->Msgbuf, "%s %s ", frametypes[c + FTOFFSET],
  549.                   (c >= 0) ? GetLocalString( &li, MSG_HEADER) : GetLocalString( &li, MSG_ERROR ));
  550. #ifdef DEBUGLOG
  551.     default:
  552.       if (c >= -3 && c <= FRTYPES)
  553.         xprsprintf (msgbuf, "zgethdr: %s @ %ld\n", frametypes[c + FTOFFSET],
  554.                     v->Rxpos);
  555.       else
  556.         xprsprintf (msgbuf, "zgethdr: Unknown type %ld @ %ld\n", (long) c,
  557.                     v->Rxpos);
  558.       dlog (v, msgbuf);
  559. #endif
  560.     }
  561.   return c;
  562. }                                /* End of short zgethdr() */
  563.  
  564. /**********************************************************
  565.  *      short zrbhdr(struct Vars *v)
  566.  *
  567.  * Receive a binary style header (type and position)
  568.  **********************************************************/
  569. short 
  570. zrbhdr (struct Vars *v)
  571. {
  572.   UBYTE *hdr = v->Rxhdr;
  573.   short c, n;
  574.   USHORT crc;
  575.  
  576. #ifdef DEBUGLOG
  577.   D (DEBUGINFO);
  578. #endif
  579.  
  580.   if ((c = zdlread (v)) & ~0xFF)
  581.     return c;
  582.   v->Rxtype = c;
  583.   crc = updcrc (c, 0);
  584.  
  585.   for (n = 4; --n >= 0;)
  586.     {
  587.       if ((c = zdlread (v)) & ~0xFF)
  588.         return c;
  589.       crc = updcrc (c, crc);
  590.       *hdr++ = c;
  591.     }
  592.   if ((c = zdlread (v)) & ~0xFF)
  593.     return c;
  594.   crc = updcrc (c, crc);
  595.   if ((c = zdlread (v)) & ~0xFF)
  596.     return c;
  597.   crc = updcrc (c, crc);
  598.   if (crc & 0xFFFF)
  599.     {
  600.       strcpy (v->Msgbuf, GetLocalString( &li, MSG_BAD_HEADER_CRC_16 ));
  601.       return ERROR;
  602.     }
  603.   return v->Rxtype;
  604. }                                /* End of short zrbhdr() */
  605.  
  606. /**********************************************************
  607.  *      short zrbhdr32(struct Vars *v)
  608.  *
  609.  * Receive a binary style header (type and position) with
  610.  * 32 bit FCS
  611.  **********************************************************/
  612. short
  613. zrbhdr32 (struct Vars *v)
  614. {
  615.   UBYTE *hdr = v->Rxhdr;
  616.   short c, n;
  617.   ULONG crc32;
  618.  
  619. #ifdef DEBUGLOG
  620.   D (DEBUGINFO);
  621. #endif
  622.  
  623.   if ((c = zdlread (v)) & ~0xFF)
  624.     return c;
  625.   v->Rxtype = c;
  626.   crc32 = 0xFFFFFFFFL;
  627.   crc32 = UPDC32 (c, crc32);
  628. #ifdef DEBUGLOG
  629.   xprsprintf (v->Msgbuf, "zrbhdr32: c=%x  crc32=%1x\n", c, crc32);
  630.   dlog (v, v->Msgbuf);
  631.   D (DEBUGINFO);
  632. #endif
  633.  
  634.   for (n = 4; --n >= 0;)
  635.     {
  636.       if ((c = zdlread (v)) & ~0xFF)
  637.         return c;
  638.       crc32 = UPDC32 (c, crc32);
  639.       *hdr++ = c;
  640. #ifdef DEBUGLOG
  641.       xprsprintf (v->Msgbuf, "zrbhdr32: c=%x  crc32=%1x\n", c, crc32);
  642.       dlog (v, v->Msgbuf);
  643.       D (DEBUGINFO);
  644. #endif
  645.     }
  646.   for (n = 4; --n >= 0;)
  647.     {
  648.       if ((c = zdlread (v)) & ~0xFF)
  649.         return c;
  650.       crc32 = UPDC32 (c, crc32);
  651. #ifdef DEBUGLOG
  652.       xprsprintf (v->Msgbuf, "zrbhdr32: c=%x  crc32=%1x\n", c, crc32);
  653.       dlog (v, v->Msgbuf);
  654.       D (DEBUGINFO);
  655. #endif
  656.     }
  657.   if (crc32 != 0xDEBB20E3)
  658.     {
  659.       strcpy (v->Msgbuf, GetLocalString( &li, MSG_BAD_HEADER_CRC_32 ));
  660.       return ERROR;
  661.     }
  662.   return v->Rxtype;
  663. }                                /* End of short zrbhdr32() */
  664.  
  665. /**********************************************************
  666.  *      short zrhhdr(struct Vars *v)
  667.  *
  668.  * Receive a hex style header (type and position)
  669.  **********************************************************/
  670. short
  671. zrhhdr (struct Vars *v)
  672. {
  673.   UBYTE *hdr = v->Rxhdr;
  674.   short c, n;
  675.   USHORT crc;
  676.  
  677. #ifdef DEBUGLOG
  678.   D (DEBUGINFO);
  679. #endif
  680.  
  681.   if ((c = zgethex (v)) < 0)
  682.     return c;
  683.   v->Rxtype = c;
  684.   crc = updcrc (c, 0);
  685.  
  686.   for (n = 4; --n >= 0;)
  687.     {
  688.       if ((c = zgethex (v)) < 0)
  689.         return c;
  690.       crc = updcrc (c, crc);
  691.       *hdr++ = c;
  692.     }
  693.   if ((c = zgethex (v)) < 0)
  694.     return c;
  695.   crc = updcrc (c, crc);
  696.   if ((c = zgethex (v)) < 0)
  697.     return c;
  698.   crc = updcrc (c, crc);
  699.   if (crc & 0xFFFF)
  700.     {
  701.       strcpy (v->Msgbuf, GetLocalString( &li, MSG_BAD_HEADER_CRC ));
  702.       return ERROR;
  703.     }
  704.   if (readock (v, 1) == '\r')
  705.     readock (v, 1);                /* Throw away possible cr/lf */
  706.   return v->Rxtype;
  707. }                                /* End of short zrhhdr() */
  708.  
  709. /**********************************************************
  710.  *      void zputhex(struct Vars *v, UBYTE c)
  711.  *
  712.  * Send a byte as two hex digits
  713.  **********************************************************/
  714. void 
  715. zputhex (struct Vars *v, UBYTE c)
  716. {
  717.   static char digits[] = "0123456789abcdef";
  718.  
  719. #ifdef DEBUGLOG
  720.   D (DEBUGINFO);
  721. #endif
  722.  
  723.   sendline (v, digits[(c >> 4) & 0x0F]);
  724.   sendline (v, digits[c & 0x0F]);
  725. }                                /* End of void zputhex() */
  726.  
  727. /**********************************************************
  728.  *      void zsendline(struct Vars *v, UBYTE c)
  729.  *
  730.  * Send character c with ZMODEM escape sequence encoding.
  731.  * Escape ZDLE, real DLE, XON, XOFF, and CR following @ (Telenet net escape)
  732.  **********************************************************/
  733. void 
  734. zsendline (struct Vars *v, UBYTE c)
  735. {
  736. #ifdef DEBUGLOG
  737.   D (DEBUGINFO);
  738. #endif
  739.  
  740.   if (v->dzap)  /* DirectZap enabled */
  741.   { 
  742. /*
  743.     if (c == ZDLE || c == ZDLEE)
  744.     {
  745.       xsendline (v, ZDLE);
  746.       c ^= 0x40;
  747.     }
  748.     xsendline (v, v->Lastzsent = c);
  749. */
  750.     switch (ZDLE_actions[c])
  751.     {
  752.       case 1:
  753.         xsendline (v, ZDLE);
  754.         c ^= 0x40;
  755.       case 0:
  756.         xsendline (v, v->Lastzsent = c);
  757.     }
  758.   }
  759.   else
  760.   {    
  761.     switch (DLE_actions[c])
  762.     {
  763.       case 2:
  764.         if (v->Lastzsent != '@')
  765.           goto sendit;
  766.         /* Fallthrough */
  767.       case 1:
  768.         xsendline (v, ZDLE);
  769.         c ^= 0x40;
  770.    sendit:
  771.       case 0:
  772.         xsendline (v, v->Lastzsent = c);
  773.     }
  774.   } 
  775. }                                /* End of void zsendline() */
  776.  
  777. /**********************************************************
  778.  *      short zgethex(struct Vars *v)
  779.  *
  780.  * Decode two lower case hex digits into an 8 bit byte value
  781.  **********************************************************/
  782. short
  783. zgethex (struct Vars *v)
  784. {
  785.   short c, n;
  786.  
  787. #ifdef DEBUGLOG
  788.   D (DEBUGINFO);
  789. #endif
  790.  
  791.   if ((n = noxrd7 (v)) < 0)
  792.     return n;
  793.   n -= '0';
  794.   if (n > 9)
  795.     n -= ('a' - ':');
  796.   if (n & ~0xF)
  797.     return ERROR;
  798.  
  799.   if ((c = noxrd7 (v)) < 0)
  800.     return c;
  801.   c -= '0';
  802.   if (c > 9)
  803.     c -= ('a' - ':');
  804.   if (c & ~0xF)
  805.     return ERROR;
  806.  
  807.   return (short) (n << 4 | c);
  808. }                                /* End of short zgethex() */
  809.  
  810. /**********************************************************
  811.  *      short zdlread(struct Vars *v)
  812.  *
  813.  * Read a byte, checking for ZMODEM escape encoding
  814.  * including CAN*5 which represents a quick abort.
  815.  **********************************************************/
  816. short 
  817. zdlread (struct Vars *v)
  818. {
  819.   short c;
  820.  
  821. #ifdef DEBUGLOG
  822.   D (DEBUGINFO);
  823. #endif
  824.  
  825.   if ((c = readock (v, v->Rxtimeout)) != ZDLE)
  826.     return c;
  827.   if ((c = readock (v, v->Rxtimeout)) < 0)
  828.     return c;
  829.   if (c == CAN && (c = readock (v, v->Rxtimeout)) < 0)
  830.     return c;
  831.   if (c == CAN && (c = readock (v, v->Rxtimeout)) < 0)
  832.     return c;
  833.   if (c == CAN && (c = readock (v, v->Rxtimeout)) < 0)
  834.     return c;
  835.   switch (c)
  836.     {
  837.     case CAN:
  838.       return GOTCAN;
  839.     case ZCRCE:
  840.     case ZCRCG:
  841.     case ZCRCQ:
  842.     case ZCRCW:
  843.       return (short) (c | GOTOR);
  844.     case ZRUB0:
  845.       return 0x7F;
  846.     case ZRUB1:
  847.       return 0xFF;
  848.     default:
  849. /*      if (v->dzap)  */
  850. /*      { */
  851. /*        return (short) ((c == ZDLEE) ? ZDLE : c); */
  852. /*      } */
  853. /*      else  */
  854. /*      { */
  855.  
  856.         if ((c & 0x60) == 0x40)
  857.           return (short) (c ^ 0x40);
  858. /*      } */
  859.       break;
  860.     }
  861.   strcpy (v->Msgbuf, GetLocalString( &li, MSG_BAD_ZMODEM_ESC_SEQ ));
  862.   return ERROR;
  863. }                                /* End of short zdlread() */
  864.  
  865. /**********************************************************
  866.  *      short noxrd7(struct Vars *v)
  867.  *
  868.  * Read a character from the modem line with timeout.
  869.  * Eat parity, XON and XOFF characters.
  870.  **********************************************************/
  871. short 
  872. noxrd7 (struct Vars *v)
  873. {
  874.   short c;
  875.  
  876. #ifdef DEBUGLOG
  877.   D (DEBUGINFO);
  878. #endif
  879.  
  880.   for (;;)
  881.   {
  882.     if ((c = readock (v, v->Rxtimeout)) < 0)
  883.       return c;
  884.     switch (c &= 0x7F)
  885.   {
  886.         case XON:
  887.         case XOFF:
  888.           continue;
  889.         default:
  890.           return c;
  891.         }
  892.     }
  893. }                                /* short noxrd7() */
  894.  
  895. /**********************************************************
  896.  *      void stohdr(struct Vars *v, long pos)
  897.  *
  898.  * Store long integer pos in Txhdr
  899.  **********************************************************/
  900. void 
  901. stohdr (struct Vars *v, long pos)
  902. {
  903. #ifdef DEBUGLOG
  904.   D (DEBUGINFO);
  905. #endif
  906.  
  907.   v->Txhdr[ZP0] = pos;
  908.   pos >>= 8;
  909.   v->Txhdr[ZP1] = pos;
  910.   pos >>= 8;
  911.   v->Txhdr[ZP2] = pos;
  912.   pos >>= 8;
  913.   v->Txhdr[ZP3] = pos;
  914. }                                /* End of void stohdr() */
  915.  
  916. /**********************************************************
  917.  *      long rclhdr(struct Vars *v)
  918.  *
  919.  * Recover a long integer from a header
  920.  **********************************************************/
  921. long 
  922. rclhdr (struct Vars *v)
  923. {
  924.   long l;
  925.  
  926. #ifdef DEBUGLOG
  927.   D (DEBUGINFO);
  928. #endif
  929.  
  930.   l = v->Rxhdr[ZP3];
  931.   l = (l << 8) | v->Rxhdr[ZP2];
  932.   l = (l << 8) | v->Rxhdr[ZP1];
  933.   l = (l << 8) | v->Rxhdr[ZP0];
  934.   return l;
  935. }                                /* End of long rclhdr() */
  936. /* End of Zm.c source */
  937.